#include <header.h>

// 某个用户10s没有说法,  踢出
typedef struct conn_s{
    int client_fd;
    time_t last_time;
}conn;

int main(){

    char *port = "8080";
    char *ip = "0.0.0.0";

    int socket_fd = socket(AF_INET, SOCK_STREAM, 0);


    struct sockaddr_in sock;
    sock.sin_family = AF_INET;
    sock.sin_port = htons(atoi(port));
    sock.sin_addr.s_addr = inet_addr(ip);
    bind(socket_fd, (struct sockaddr *)&sock, sizeof(sock));

    listen(socket_fd, 10);

    conn list[100];//用来记录所有的用户链接
    memset(list,0, sizeof(list));
    int size = 0;

    // 定义一个base_set保存下一次循环要监听的文件描述符集合
    fd_set base_set;
    FD_ZERO(&base_set);
    FD_SET(socket_fd, &base_set);
    while(1){

        fd_set set;
        FD_ZERO(&set);
        memcpy(&set, &base_set, sizeof(base_set));


        struct timeval  tv ;
        tv.tv_sec = 1;
        tv.tv_usec = 0;
        select(100, &set, NULL, NULL, &tv);

        if(FD_ISSET(socket_fd, &set)){
            // 有新链接进来
            int net_fd = accept(socket_fd, NULL, NULL);
            // 把新链接加入监听
            FD_SET(net_fd, &base_set);
            // 保存net_fd到list
            list[size].client_fd = net_fd;
            time(&list[size].last_time);
            size++;
        }

        // 遍历所有的用户链接
        for(int i=0; i<size; i++){
            int client_fd = list[i].client_fd;

            // 判断当前遍历的用户, 是不是就绪了, 如果就绪 : 读信息-> 转发
            if(FD_ISSET(client_fd, &set)){
                // 读取客户端发送过来的信息
                char buf[100] = {0};
                ssize_t ret = recv(client_fd, buf, sizeof(buf), 0);
                // TODO: stm32, 手机(获取/删除) -> 处理
                if(ret == 0){
                    // 这个客户端可读, 读到数据了吗? 没有 -> 说明断开链接

                    // 移除监听, close, list_fd清除
                    FD_CLR(client_fd, &base_set);
                    close(list[i].client_fd);

                    for(int k=i; k<size; k++){
                        list[k] = list[k+1];
                    }

                    size--;
                    i--;
                    continue;
                }

                //更新最后的说话时间 
                time(&list[i].last_time);


                // 转发
                for(int j=0; j<size; j++){
                    if(i != j){
                        // 不是自己 -> 转发
                        send(list[j].client_fd, buf,sizeof(buf), 0);
                    }
                }

            }
        }

        // 遍历所有用户, 看是否超时
        time_t  now_time;
        time(&now_time);

        for(int i=0; i<size; i++){
            if(now_time - list[i].last_time > 10){
                // 超过10s没有说话-> 踢出
                //
                // 移除监听, close, list_fd清除
                FD_CLR(list[i].client_fd, &base_set);
                close(list[i].client_fd);

                for(int k=i; k<size; k++){
                    list[k] = list[k+1];
                }

                size--;
                i--;
            }
        }
    }


    return 0;
}

